/*
* Copyright (c) 2020 The canvas Authors. All rights reserved.
  Use of this source code is governed by a BSD-style license that can be
  found in the LICENSE file.

* Author:         dzlua - https://gitee.com/dzlua/canvas.git
* Email:          505544956@qq.com
* FileName:       dynamic_library.cc
* Create Time:    2020/01/04 09:27:01
* Description:    /
*/

#include "dynamic_library.h"

#include <canvas.h>

namespace cvs {

// windows
#if defined(I_OS_WIN)
  #include <windows.h>
  typedef HMODULE DLHandle;
  DLHandle dl_open(const char *pname) { return LoadLibraryA(pname); }
  void dl_close(DLHandle handle) { if (handle) FreeLibrary(handle); }
  void* dl_proc(DLHandle handle, const char *fname) { if (!handle) return 0; return (void*)GetProcAddress(handle, fname); }

// linux
#elif defined(I_OS_LINUX)
  #include <dlfcn.h>
  typedef void* DLHandle;
  DLHandle dl_open(const char *pname) { return dlopen(pname, RTLD_NOW | RTLD_GLOBAL); }
  void dl_close(DLHandle handle) { if (handle) dlclose(handle); }
  void* dl_proc(DLHandle handle, const char *fname) { if (!handle) return 0; return dlsym(handle, fname); }

// others
#else

#endif

} // end namespace cvs

namespace cvs {
  class DynamicLibrary : public IDynamicLibrary {
    public:
      DynamicLibrary() : handle_(0) {}
      ~DynamicLibrary() { close(); }
    public:
      virtual void release() override { delete this; }
      virtual bool open(const char *pname) override { handle_ = dl_open(pname); return !!handle_; }
      virtual void* proc(const char *fname) override { return dl_proc(handle_, fname); }
      virtual void close() override { if(handle_) { dl_close(handle_); handle_ = 0; } }
      virtual bool opened() const override { return !!handle_; }
    protected:
      DLHandle handle_;
  };
  IDynamicLibrary* IDynamicLibrary::new_instance() { return new DynamicLibrary; }
} // end namespace cvs